package com.person.yhzs.family.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.person.yhzs.common.Constants;
import com.person.yhzs.common.ReturnData;
import com.person.yhzs.common.page.PageRequest;
import com.person.yhzs.common.page.PageResponse;
import com.person.yhzs.exception.BaseException;
import com.person.yhzs.family.entity.Family;
import com.person.yhzs.family.entity.UserFamily;
import com.person.yhzs.family.entity.dto.FamilyDto;
import com.person.yhzs.family.entity.dto.QueryDto;
import com.person.yhzs.family.entity.vo.FamilyPersonTreeModelVo;
import com.person.yhzs.family.entity.vo.FamilyVo;
import com.person.yhzs.family.mapper.FamilyMapper;
import com.person.yhzs.family.service.FamilyService;
import com.person.yhzs.user.entity.User;
import com.person.yhzs.user.entity.dto.UserDto;
import com.person.yhzs.user.entity.vo.UserVo;
import com.person.yhzs.user.mapper.UserMapper;
import com.person.yhzs.user.service.UserService;
import com.person.yhzs.user.service.impl.UserServiceImpl;
import com.person.yhzs.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author luolin
 * @version 1.0.0
 * @ClassName FamilyServiceImpl.java
 * @Description TODO
 * @createTime 2022年05月30日 11:35:00
 */
@Service
public class FamilyServiceImpl implements FamilyService {
//    static final Logger LOGGER = LoggerFactory.getLogger(FamilyServiceImpl.class);

    @Resource
    UserService userService;

    @Resource
    FamilyMapper familyMapper;

    @Resource
    UserMapper userMapper;

    @Override
    @Transactional
    public Integer addFamily(Family family,String userId) {
        if (family.getFamilyCreateTime() == null){
            String curDT = DateUtil.getCurrTime();
            family.setFamilyCreateTime(curDT);
        }
        family.setFamilyCreateUserId(Integer.valueOf(userId));

        Long familyIsHave = familyMapper.checkFamilyIsHave(family.getFamilyName());
        if(familyIsHave > 0){
            throw new BaseException("家谱已经存在！");
        }
        Integer addResult = familyMapper.insertFamilyTemplate(family);
        Long familyId = family.getId().longValue();
        Long uid = Long.valueOf(userId);
        Long checkResult = familyMapper.checkJoinFamily(uid,familyId);
        if(checkResult <= 0){
            UserFamily userFamily = new UserFamily();
            userFamily.setFamilyId(familyId);
            userFamily.setUserId(uid);
            familyMapper.joinFamily(userFamily);
        }
        return addResult;
    }

    @Override
    public Long editFamily(Family family) {
        Long aLong = null;
        if(family.getId() != null){
            aLong = familyMapper.editFamily(family);
        }else{
            throw new BaseException("没有Id标识");
        }
        return aLong;
    }

    @Override
    public FamilyVo queryFamily(FamilyDto familyDto) {
        FamilyVo familyVo = familyMapper.queryFamilyOne(familyDto);
        return familyVo;
    }

    @Override
    public List<FamilyVo> queryFamilyList(FamilyDto familyDto, Integer pageIndex, Integer pageSize) {
        List<FamilyVo> familyVos = familyMapper.queryFamilyList(familyDto,pageIndex,pageSize);
        return familyVos;
    }

    @Override
    public Long listFamilyCount(FamilyDto familyDto) {
        Long num = familyMapper.listFamilyCount(familyDto);
        return num;
    }

    @Override
    public PageResponse<FamilyVo> queryFamilyPage(PageRequest<QueryDto> queryDto) {

        PageResponse<FamilyVo> pageable = new PageResponse<>();
        Integer pageIndex = Long.valueOf(queryDto.getOffset()).intValue();
        Integer pageSize = queryDto.getPageSize();

        FamilyDto familyDto = new FamilyDto();
        String familyName = queryDto.getData().getFamilyName();
        String userName = queryDto.getData().getUserName();
        Boolean sortTimeDesc = queryDto.getData().getSortTimeDesc();

        if(familyName != null && familyName != ""){
            familyDto.setFamilyName("%" + familyName+ "%");
        }
        if(userName != null && familyName != ""){
            familyDto.setUserName("%" + userName+ "%");
        }
        if(sortTimeDesc == null){
            familyDto.setSortTimeDesc(Constants.DESC);
        }else{
            familyDto.setSortTimeDesc(sortTimeDesc);
        }
        Long total = familyMapper.listFamilyCount(familyDto);
        
        List<FamilyVo> familyVos = null;
        if(total > 0){
            familyVos = familyMapper.queryFamilyList(familyDto,pageIndex,pageSize);
        }
        pageable.setData(familyVos);
        pageable.setTotalElements(total);
        pageable.setPageIndex(queryDto.getPageIndex());
        pageable.setPageSize(queryDto.getPageSize());
       // pageable.set
        return pageable;
    }

    @Override
    public List<Map<String,String>> queryFamilyWords(Long familyId) {

        FamilyDto familyDto = new FamilyDto();
        familyDto.setId(familyId.intValue());
        FamilyVo familyVo = familyMapper.queryFamilyOne(familyDto);

        List<Map<String,String>> parse = (List<Map<String,String>>) JSONArray.parse(familyVo.getGenerationWords());
        if (parse == null) {
            parse = new ArrayList<Map<String,String>>();
        }
        return parse;
    }

    @Transactional
    @Override
    public UserFamily joinFamily(Long userId, Long familyId) {
        UserFamily userFamily = new UserFamily();
        Long checkResult = familyMapper.checkJoinFamily(userId,familyId);
        FamilyDto familyDto = new FamilyDto();
        if(familyId == null){
            throw new BaseException("未指定需要加入的家谱！");
        }
        familyDto.setId(familyId.intValue());
        FamilyVo vo = this.queryFamily(familyDto);
        if(checkResult > 0){
            throw  new BaseException("已在家谱中");
        }else if(vo == null){
            throw  new BaseException("没有该家谱");
        } else{
            userFamily.setUserId(userId);
            userFamily.setFamilyId(familyId);
            familyMapper.joinFamily(userFamily);
        }
        return userFamily;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void familyAddPerson(Long familyId, Integer type, UserDto userDto) {

        // 校验该人员是否存在（不存在则新增，存在，则查询出人员id）

        // 用户在世状态为必传
        if(userDto.getUserDie() == null){
            throw new BaseException("用户是否去世为必传字段！");
        }else if(userDto.getUserDie() != Constants.DIE && userDto.getUserDie() != Constants.BE_LIVING){
            throw new BaseException("用户是否去世字段错误！");
        }

        // 判断人员是否在世，不在世的可以不用输入手机号
        if(userDto.getUserDie() == Constants.BE_LIVING && StringUtils.isBlank(userDto.getUserPhone())){  // 在世，必须输入手机号
            throw new BaseException("手机号不能为空");
        }

        // 再次验证是否存在手机号
        Boolean isExists = this.checkPhone(userDto.getUserPhone());
        // 两次都是存在手机号，则修改人员信息
        if(userDto.getExistsPhone() == true && isExists == true ){
            User user = userMapper.queryUserByPhone(userDto.getUserPhone());
            if(user != null){
                // 检查该人员是否已经在该家谱中
                Long hasJoined = familyMapper.checkJoinFamily(Long.valueOf(user.getId()), familyId);
                if(hasJoined > 0){
                    throw new BaseException("该手机号的所属人员已在本家谱中！");
                }else{
                    userDto.setId(user.getId());
                    // 修改人员信息
                    userService.updateUser(userDto);
                }
            }else{
                throw new BaseException("手机号重复处理错误！请重试！");
            }
        }
        // 前端校验存在手机号，但后台校验不存在手机号，表示该手机号已被删除，可直接新增人员信息
        else if(userDto.getExistsPhone() == true && isExists == false){
            userService.insertUser(userDto);
        }
        // 前端校验不存在手机号，但后台校验存在手机号，表示手机号已被使用，需要重新处理
        else if(userDto.getExistsPhone() == false && isExists == true){
            throw new BaseException("该手机号已被使用！请重新处理！");
        }
        // 两次校验都不存在手机号，直接新增人员信息
        else{
            userService.insertUser(userDto);
        }

        // 检查人员是否已在家谱中
        Long checkResult = familyMapper.checkJoinFamily(Long.valueOf(userDto.getId()),familyId);
        if(checkResult > 0){
            throw new BaseException("该人员已在家谱中");
        }else{
            // 将成员信息，加入到家谱
            this.joinPerson(familyId,type,userDto);
        }
    }

    @Override
    public Boolean checkPhone(String phone) {
        Long aLong = userMapper.checkPhone(phone);
        if(aLong > 0){
            return true;
        }else{
            return false;
        }
    }

    @Override
    public Long checkIdCard(String idCard) {
        Long aLong = userMapper.checkIdCard(idCard);
        return aLong;
    }

    @Transactional
    @Override
    public FamilyPersonTreeModelVo checkHaveOption(Long familyId, Long userId) {
        FamilyPersonTreeModelVo familyPersonTreeModelVo = familyMapper.selectUserFamilyInfo(familyId, userId);
        return familyPersonTreeModelVo;
    }

    @Override
    public FamilyPersonTreeModelVo checkHaveOptionByRelationId(Long relationId) {
        FamilyPersonTreeModelVo familyPersonTreeModelVo = familyMapper.selectUserFamilyInfoByRelationId(relationId);
        return familyPersonTreeModelVo;
    }

    @Override
    public List<FamilyPersonTreeModelVo> getFamilyPerson(Long familyId) {

        List<FamilyPersonTreeModelVo> familyPersonList = familyMapper.getFamilyPersonList(familyId);

        for (FamilyPersonTreeModelVo vo : familyPersonList) {
//            if(vo.getIsRemove() != null && vo.getIsRemove() == 1){  // 被移除的人员
//                UserVo tempUser = new UserVo();
//                tempUser.setId(vo.getUserId().intValue());
//                vo.setUser(tempUser);
//            }

        }

        System.err.println(familyPersonList);
//        if(){
//
//        }
        return familyPersonList;
    }

    @Override
    public FamilyPersonTreeModelVo getFamilyPersonOne(Long familyId, Long userId) {
        FamilyPersonTreeModelVo familyPersonOne = familyMapper.getFamilyPersonOne(familyId, userId);
        return familyPersonOne;
    }

    @Override
    public FamilyPersonTreeModelVo getFamilyPersonOneByRelationId(Long relationId) {
        FamilyPersonTreeModelVo familyPersonOne = familyMapper.getFamilyPersonOneByRelationId(relationId);
        return familyPersonOne;
    }

    @Override
    public void removeFamilyPersonSelf(Long familyId, Long userId) {
        Long childNumber = familyMapper.checkFamilyPersonChild(familyId, userId);
        if(childNumber != null && childNumber == 0){    // 没有子数据，则删除
            Long aLong = familyMapper.deleteFamilyPersonSelf(familyId, userId);
            if(aLong <= 0){
                throw new BaseException("删除失败！请联系管理员");
            }
        }else{  // 有子数据，则移除（只修改不删除）
            Long aLong = familyMapper.removeFamilyPersonSelf(familyId, userId);
            if (aLong <= 0){
                throw new BaseException("移除失败！请联系管理员");
            }
        }
    }

    @Override
    public void removeFamilyPersonSelfByRelationId(Long relationId) {
        Long childNumber = familyMapper.checkFamilyPersonChildRelation(relationId);
        if(childNumber != null && childNumber == 0){    // 没有子数据，则删除
            Long aLong = familyMapper.deleteFamilyPersonSelfRelation(relationId);
            if(aLong <= 0){
                throw new BaseException("删除失败！请联系管理员");
            }
        }else{  // 有子数据，则移除（只修改不删除）
            Long aLong = familyMapper.removeFamilyPersonSelfByRelationId(relationId);
            if (aLong <= 0){
                throw new BaseException("移除失败！请联系管理员");
            }
        }
    }

    @Override
    @Transactional
    public void replaceFamilyPersonByRelationId(Long relationId, Long replaceId) {
        // 先更换家谱关系人员的userId为replaceId
        Long aLong = familyMapper.updateFamilyRelationUserId(relationId, replaceId);
        if(aLong != 1){
            throw new BaseException("替换用户唯一标识出错！");
        }
    }

    @Override
    @Transactional
    public void replaceFamilyPersonMate(Long relationId, Long replaceId) {
        // 先更换家谱关系人员的userId为replaceId
        Long aLong = familyMapper.updateFamilyRelationMateId(relationId, replaceId);
        if(aLong != 1){
            throw new BaseException("替换用户唯一标识出错！");
        }
    }

    @Override
    @Transactional
    public void removeFamilyPersonSelfAndChild(Long familyId, Long pId) {
        Set<Long> sets = new HashSet<>();
        sets.add(pId);
        Set<Long> longSet = new HashSet<>();
        Set<Long> setList = this.getDeleteId(familyId, sets, longSet);
        setList.addAll(sets);
        familyMapper.deleteFamilyPersonBatch(familyId,setList);
        System.err.println("调试：" + setList);
    }

    @Override
    public void removeFamilyPersonSelfMate(Long relationId) {
        Long aLong = familyMapper.deleteFamilyPersonMateByRelationId(relationId);
        if(aLong <= 0){
            throw new BaseException("移除失败！");
        }
    }

    @Transactional
    @Override
    public void deleteFamily(Long familyId) {
        Long familyPersonNum = familyMapper.checkFamilyNumber(familyId);
        if(familyPersonNum > 1){
            throw new BaseException("家谱中存在1个以上的家谱成员，不能删除！");
        }else{
            Long delFamilyResult = familyMapper.deleteFamily(familyId);
            Long delFamilyPersonResult = familyMapper.deleteFamilyPersonAll(familyId);
//            if(delFamilyResult <= 0){
//                throw new BaseException("删除家谱信息失败！");
//            }
//            if(delFamilyPersonResult <= 0){
//                throw new BaseException("删除家谱人员失败！");
//            }
        }
    }

    /* 加入人员 */
    @Transactional
    void joinPerson(Long familyId,Integer type,UserDto userDto){

        // 检查该人员信息有没有被添加过，是否已经添加过了配偶或者parent
        Long relationId = userDto.getRelationId();

        /*  替换 */
        if(type == 0){
            // 替换配偶
            if(userDto.getOptionMate() == null || userDto.getOptionMate() == false){
                this.replaceFamilyPersonByRelationId(relationId,Long.valueOf(userDto.getId()));
            }
            // 替换人员
            else if(userDto.getOptionMate() == true){
                this.replaceFamilyPersonMate(relationId,Long.valueOf(userDto.getId()));
            }
            return;
        }

        // 晚辈
        if(type == Constants.CHILDREN){
            this.addChild(familyId,Long.valueOf(userDto.getId()),relationId);
        }
        // 平辈
        else if(type == Constants.BROTHER){
            this.addBrother(familyId,Long.valueOf(userDto.getId()),relationId);
        }
        // 配偶
        else if(type == Constants.MATE){
            this.addMate(familyId,Long.valueOf(userDto.getId()),relationId);
        }
        // 父辈
        else if(type == Constants.PARENT){
            this.addParent(familyId,Long.valueOf(userDto.getId()),relationId);
        }
    }

    /**
     * 添加父辈
     * @param familyId
     * @param userId
     * @param relationId
     */
    @Transactional
    void addParent(Long familyId,Long userId,Long relationId){
        // 当前关系id的关系信息包括（人员信息、父关系id、配偶id等）
        FamilyPersonTreeModelVo familyPersonTreeModelVo = this.checkHaveOptionByRelationId(relationId); // 通过关系id查找家庭信息
        Long relationPId1 = familyPersonTreeModelVo.getRelationPId();
        if(relationPId1 != null){   // 若当前关系有父关系id，则表示存在父关系，需要添加父辈的平辈
            // 添加父辈步骤
            //先拿到父关系的id
            Long relationPId = familyPersonTreeModelVo.getRelationPId();
            // 通过父关系id，给父关系添加平辈等同于添加父辈
            this.addBrother(familyId,userId,relationPId);
        }else{  // 若没有父关系id，则表示添加的为根节点

            // 第一步：先增加parent和家谱的关系
            UserFamily userFamily = this.joinFamily(userId, familyId);
            // 第二步：关联parent和当前人员的关系
            // 把当前操作的关系id关联为父关系id
            Long relationPId = userFamily.getRelationId();
            familyMapper.updateFamilyUserRelationPId(relationId,relationPId);
        }
    }

    /**
     * 添加配偶
     * @param familyId
     * @param userId
     * @param relationId
     */
    @Transactional
    void addMate(Long familyId,Long userId,Long relationId){
        // 当前关系id的关系信息包括（人员信息、父关系id、配偶id等）
        FamilyPersonTreeModelVo familyPersonTreeModelVo = this.checkHaveOptionByRelationId(relationId); // 通过关系id查找家庭信息
        if(familyPersonTreeModelVo.getMateId() != null){
            throw new BaseException("已经拥有配偶，不可添加配偶信息");
        }else{
            Long mateId = userId;
            familyMapper.updateFamilyPersonMateByRelationId(relationId,mateId);
        }
    }

    /**
     * 新增平辈
     * @param familyId
     * @param userId
     * @param relationId
     */
    @Transactional
    void addBrother(Long familyId,Long userId,Long relationId){
        // 获取当前用户的关系
        FamilyPersonTreeModelVo userRelation = familyMapper.selectUserFamilyByRelationId(relationId);

        // 有没有父Id
        if(userRelation.getRelationPId() != null){
            // 有父Id则直接添加
            familyMapper.insertFamilyPerson(familyId,userId,userRelation.getRelationPId());
        }else{
            throw new BaseException("未找到父辈，添加兄弟信息有误！请先添加父辈！");
        }
    }

    /**
     * 新增晚辈
     * @param familyId
     * @param userId
     * @param relationId
     */
    @Transactional
    void addChild(Long familyId,Long userId,Long relationId){
        Long aLong = familyMapper.insertFamilyPerson(familyId, userId, relationId);
        if(aLong <= 0){
            throw new BaseException("新增失败！");
        }
    }

    /**
     * @Description 获取需要删除的relationId
     * @Author luolin
     * @Date 2022/10/24 10:17
     **/
    private Set<Long> getDeleteId(Long familyId,Set<Long> pIds,Set<Long> resultIds){
        Set<Long> userIdSet = new HashSet<>();
        for (Long pId:pIds) {
            List<Long> userIds = familyMapper.selectBatchUserByPid(familyId, pId);
            Set<Long> tempSet = new HashSet<>(userIds);
            userIdSet.addAll(tempSet);
        }
//        Set<Long> ids = new HashSet<>(userIdSet);
        if(userIdSet.size() > 0){
            resultIds.addAll(userIdSet);
            return this.getDeleteId(familyId,userIdSet,resultIds);
        }else{
            return resultIds;
        }
    }

}
